﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using UtilZ.Dotnet.DBIBase;
using UtilZ.Dotnet.Ex.ZLog;

namespace UtilZ.Dotnet.DBSQLite
{
    /// <summary>
    /// SQLite DbConnectionPool连接池
    /// </summary>
    internal class SQLiteDbConnectionPool : DbConnectionPoolAbs
    {
        /// <summary>
        /// 连接对象集合池
        /// </summary>
        private readonly BlockingCollection<PrimitiveDbConnection> _conPool = null;

        /// <summary>
        /// 连接池有效性ID
        /// </summary>
        private int _poolValidID;

        /// <summary>
        /// 连接池有效性ID锁
        /// </summary>
        private readonly object _poolValidIDLock = new object();

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="config">数据库配置</param>
        /// <param name="interaction">数据库交互实例</param>
        public SQLiteDbConnectionPool(DatabaseConfig config, IDBInteraction interaction)
             : base(config, interaction)
        {
            this._conPool = new BlockingCollection<PrimitiveDbConnection>();
            this._poolValidID = 1;
            this.InitDbConnection(config, this._poolValidID);
        }

        private void InitDbConnection(DatabaseConfig config, int poolValidID)
        {
            this._conPool.Add(base.CreateConnection(DBVisitType.W, this._poolValidID));
        }

        /// <summary>
        /// 重置连接
        /// </summary>
        protected override void PrimitiveResetDbConnection()
        {
            lock (this._poolValidIDLock)
            {
                const int millisecondsTimeout = 0;
                PrimitiveDbConnection pcon;
                if (this._config.ReadConCount >= DBConstant.ReadConCount)
                {
                    while (this._conPool.TryTake(out pcon, millisecondsTimeout))
                    {
                        pcon.DbConnection.Close();
                    }
                }

                this._poolValidID++;
                this.InitDbConnection(base._config, this._poolValidID);
            }
        }

        /// <summary>
        /// 获取数据库访问连接对象
        /// </summary>
        /// <param name="visitType">数据库访问类型</param>
        /// <returns>数据库访问连接对象</returns>
        protected override PrimitiveDbConnection PrimitiveGetDbConnection(DBVisitType visitType)
        {
            PrimitiveDbConnection conObj;
            if (!this._conPool.TryTake(out conObj, this._config.GetConTimeout))
            {
                throw new ApplicationException("从连接池获取读连接超时");
            }

            try
            {
                if (conObj.DbConnection.State != ConnectionState.Open)
                {
                    conObj.DbConnection.Open();
                }
            }
            catch (Exception ex)
            {
                this.ReleaseDbConnection(conObj, visitType);
                throw new ApplicationException("打开数据库连接异常", ex);
            }

            return conObj;
        }

        /// <summary>
        /// 释放数据库访问连接对象
        /// </summary>
        /// <param name="pcon">数据库访问连接对象</param>
        /// <param name="visitType">数据库访问类型</param>
        protected override void PrimitiveReleaseDbConnection(PrimitiveDbConnection pcon, DBVisitType visitType)
        {
            this._conPool.Add(pcon);
        }



        /// <summary>
        /// 释放资源
        /// </summary>
        /// <param name="isDisposing">是否释放资源标识</param>
        protected override void Dispose(bool isDisposing)
        {
            try
            {
                this._conPool.Dispose();
            }
            catch (Exception ex)
            {
                ZLoger.Error(ex);
            }
        }
    }
}
